package cn.seaboot.admin.mvc;

import cn.seaboot.commons.core.FastJsonUtils;

import java.io.Serializable;

/**
 * 返回值封装
 * <p>
 * 业务终止有两种方式：
 * <p>
 * 1、通过异常抛出，由管理类统一处理；
 * 2、通过 return 的方式，正常结束，当前类主要封装这种执行结果。
 *
 * <li>2019-10-15 17:21   修订</li>
 * <li>2020-03-12 12:01   toString()函数功能修复，兼容所有类型数据</li>
 * <li>2025-04-09 12:01   引入 RFC-7807 规范，增加 Problem 类，当前类删除部分异常常量</li>
 *
 * @author Mr.css
 * @version 2018-10-12 17:19      提交
 */
public class Result implements Serializable {
    private static final long serialVersionUID = -760367937851024727L;

    /**
     * 操作成功，码值：0，或者200
     */
    public static final Result SUCCEED = new Result(0, "操作成功!");

    /**
     * 所有未处理的异常都会转为这个，码值： 1，或者 500
     */
    public static final Result FAILED = new Result(1, "操作失败!");

    /**
     * 无效的操作
     * <p>
     * 执行成功，但是未发生任何数据变化，改动前和改动之后的状态完全一致。
     * <p>
     * 通常指数据库 update 受影响行数为 0 的情况。
     */
    public static final Result NOT_MODIFIED = new Result(304, "无效的操作！");

    /**
     * 多状态
     * <p>
     * 部分内容成功处理，但另一部分失败（即“部分成功”）
     */
    public static final Result MULTI_STATUS = new Result(207, "部分成功！");

    /**
     * 接收成功
     * <p>
     * 当请求已接收并开始处理，但最终结果需异步返回（如后台任务）。
     * 若处理过程中部分操作已明确成功，但整体结果尚未确定，可用 202。
     */
    public static final Result ACCEPTED = new Result(202, "已提交至后台处理！");

    /**
     * 操作成功，码值：0，或者200
     * <p>
     * 只是一个兼容配置，因为很多系统会这么定
     */
    public static final Result SC_OK = new Result(200, "操作成功!");

    /**
     * 数据未找到
     */
    public static final Result PAYMENT_REQUIRED = new Result(402, "数据未找到!");

    /**
     * 数据未找到
     */
    public static final Result FORBIDDEN = new Result(403, "无权操作!");

    /**
     * 数据未找到
     */
    public static final Result NOT_FOUND = new Result(404, "数据未找到!");

    /**
     * 资源曾存在但已被永久删除
     */
    public static final Result GONE = new Result(410, "资源丢失!");

    /**
     * 服务器暂时无法提供资源	过载、维护、第三方API故障
     */
    public static final Result SERVICE_UNAVAILABLE = new Result(503, "资源丢失!");

    /**
     * 当请求语法正确，但业务逻辑导致部分操作失败（如参数验证失败）
     */
    public static final Result UNPROCESSABLE_ENTITY = new Result(422, "语义化错误!");

    /**
     * 未知的错误
     */
    public static final Result INTERNAL_SERVER_ERROR = new Result(500, "未知的错误，请联系管理员!");

    /**
     * 操作成功
     *
     * @param data 数据
     * @return result
     */
    public static Result succeed(Object data) {
        return new Result(0, data);
    }

    /**
     * 操作失败
     *
     * @param data 数据
     * @return result
     */
    public static Result failed(Object data) {
        return new Result(1, data);
    }

    /**
     * 根据数据库受影响行数，判定返回结果
     *
     * @param row     数据库受影响行数
     * @param success 成功提示
     * @param fail    失败提示
     * @return result
     */
    public static Result doUpdate(int row, Object success, String fail) {
        return row > 0 ? Result.succeed(success) : Result.failed(fail);
    }

    /**
     * 根据数据库受影响行数，判定返回结果
     *
     * @param row     数据库受影响行数
     * @param success 成功提示
     * @return result
     */
    public static Result doUpdate(int row, Object success) {
        return row > 0 ? Result.succeed(success) : Result.FAILED;
    }

    /**
     * 根据数据库受影响行数，判定返回结果
     *
     * @param row 数据库受影响行数
     * @return result
     */
    public static Result doUpdate(int row) {
        return row > 0 ? Result.SUCCEED : Result.NOT_MODIFIED;
    }

    /**
     * 根据数据库受影响行数，判定返回结果
     *
     * @param row 数据库受影响行数
     * @return result
     */
    public static Result doUpdate(Integer row) {
        return row > 0 ? Result.SUCCEED : Result.NOT_MODIFIED;
    }

    /**
     * 操作成功
     *
     * @return result
     */
    public static Result succeed() {
        return SUCCEED;
    }

    /**
     * 操作失败
     *
     * @return result
     */
    public static Result failed() {
        return FAILED;
    }

    private int code;
    private Object data;

    public Result(int code, Object data) {
        this.code = code;
        this.data = data;
    }

    public int getCode() {
        return code;
    }

    public void setCode(int code) {
        this.code = code;
    }

    public Object getData() {
        return data;
    }

    public void setData(Object data) {
        this.data = data;
    }

    @Override
    public String toString() {
        return FastJsonUtils.toJSONString(this);
    }
}
